home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1992, 1993 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this software; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* NOTE!!! AIX requires this to be the first thing in the file.
- * Do not put ANYTHING before it!
- */
- #if !defined (__GNUC__) && defined (_AIX)
- #pragma alloca
- #endif
-
- static char rx_version_string[] = "GNU Rx version 0.03";
-
- /* ``Too hard!''
- * -- anon.
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #ifndef isgraph
- #define isgraph(c) (isprint (c) && !isspace (c))
- #endif
- #ifndef isblank
- #define isblank(c) ((c) == ' ' || (c) == '\t')
- #endif
-
- #include <sys/types.h>
- #include <stdio.h>
- #include "rx.h"
-
- #undef MAX
- #undef MIN
- #define MAX(a, b) ((a) > (b) ? (a) : (b))
- #define MIN(a, b) ((a) < (b) ? (a) : (b))
-
- typedef char boolean;
- #define false 0
- #define true 1
-
-
- /* This page is decls to the interesting subsystems and lower layers
- * of rx. Everything which doesn't have a public counterpart in
- * regex.c is declared here.
- *
- * A useful (i hope) system is obtained by removing all or part of the regex.c
- * reimplementation and making these all extern. I think this package
- * could be used to implement on-line lexers and parsers and who knows what
- * else.
- */
- /* In the definitions, these functions are qualified by `RX_DECL' */
- #define RX_DECL static
-
- #ifdef __STDC__
-
- RX_DECL int rx_bitset_is_subset (int size, rx_Bitset a, rx_Bitset b);
- RX_DECL void rx_bitset_null (int size, rx_Bitset b);
- RX_DECL void rx_bitset_universe (int size, rx_Bitset b);
- RX_DECL void rx_bitset_complement (int size, rx_Bitset b);
- RX_DECL void rx_bitset_assign (int size, rx_Bitset a, rx_Bitset b);
- RX_DECL void rx_bitset_union (int size, rx_Bitset a, rx_Bitset b);
- RX_DECL void rx_bitset_intersection (int size,
- rx_Bitset a, rx_Bitset b);
- RX_DECL void rx_bitset_difference (int size, rx_Bitset a, rx_Bitset b);
- RX_DECL unsigned long rx_bitset_hash (int size, rx_Bitset b);
- RX_DECL struct rx_hash_item * rx_hash_find (struct rx_hash * table,
- unsigned long hash,
- void * value,
- struct rx_hash_rules * rules);
- RX_DECL struct rx_hash_item * rx_hash_store (struct rx_hash * table,
- unsigned long hash,
- void * value,
- struct rx_hash_rules * rules);
- RX_DECL void rx_hash_free (struct rx_hash_item * it,
- struct rx_hash_rules * rules);
- RX_DECL rx_Bitset rx_cset (struct rx *rx);
- RX_DECL rx_Bitset rx_copy_cset (struct rx *rx, rx_Bitset a);
- RX_DECL void rx_free_cset (struct rx * rx, rx_Bitset c);
- RX_DECL struct rexp_node * rexp_node (struct rx *rx,
- enum rexp_node_type type);
- RX_DECL struct rexp_node * rx_mk_r_cset (struct rx * rx,
- rx_Bitset b);
- RX_DECL struct rexp_node * rx_mk_r_concat (struct rx * rx,
- struct rexp_node * a,
- struct rexp_node * b);
- RX_DECL struct rexp_node * rx_mk_r_alternate (struct rx * rx,
- struct rexp_node * a,
- struct rexp_node * b);
- RX_DECL struct rexp_node * rx_mk_r_opt (struct rx * rx,
- struct rexp_node * a);
- RX_DECL struct rexp_node * rx_mk_r_star (struct rx * rx,
- struct rexp_node * a);
- RX_DECL struct rexp_node * rx_mk_r_2phase_star (struct rx * rx,
- struct rexp_node * a,
- struct rexp_node * b);
- RX_DECL struct rexp_node * rx_mk_r_side_effect (struct rx * rx,
- rx_side_effect a);
- RX_DECL struct rexp_node * rx_mk_r_data (struct rx * rx,
- void * a);
- RX_DECL void rx_free_rexp (struct rx * rx, struct rexp_node * node);
- RX_DECL struct rexp_node * rx_copy_rexp (struct rx *rx,
- struct rexp_node *node);
- RX_DECL struct rx_nfa_state * rx_nfa_state (struct rx *rx);
- RX_DECL void rx_free_nfa_state (struct rx_nfa_state * n);
- RX_DECL struct rx_nfa_state * rx_id_to_nfa_state (struct rx * rx,
- int id);
- RX_DECL struct rx_nfa_edge * rx_nfa_edge (struct rx *rx,
- enum rx_nfa_etype type,
- struct rx_nfa_state *start,
- struct rx_nfa_state *dest);
- RX_DECL void rx_free_nfa_edge (struct rx_nfa_edge * e);
- RX_DECL void rx_free_nfa (struct rx *rx);
- RX_DECL int rx_build_nfa (stru }
-
-
- case r_concat:
- {
- struct rx_nfa_state *shared = 0;
- return
- (rx_build_nfa (rx, rexp->params.pair.left, start, &shared)
- && rx_build_nfa (rx, rexp->params.pair.right, &shared, end));
- }
-
- case r_alternate:
- {
- struct rx_nfa_state *ls = 0;
- struct rx_nfa_state *le = 0;
- struct rx_nfa_state *rs = 0;
- struct rx_nfa_state *re = 0;
- return (rx_build_nfa (rx, rexp->params.pair.left, &ls, &le)
- && rx_build_nfa (rx, rexp->params.pair.right, &rs, &re)
- && rx_nfa_edge (rx, ne_epsilon, *start, ls)
- && rx_nfa_edge (rx, ne_epsilon, *start, rs)
- && rx_nfa_edge (rx, ne_epsilon, le, *end)
- && rx_nfa_edge (rx, ne_epsilon, re, *end));
- }
-
- case r_side_effect:
- edge = rx_nfa_edge (rx, ne_side_effect, *start, *end);
- if (!edge)
- return 0;
- edge->params.side_effect = rexp->params.side_effect;
- return 1;
- };
- }
-
-
- /* NAME_RX->NFA_STATES identifies all nodes with non-epsilon transitions.
- * These nodes can occur in super-states. All nodes are given an integer id.
- * The id is non-negative if the node has non-epsilon out-transitions, negative
- * otherwise (this is because we want the non-negative ids to be used as
- * array indexes in a few places).
- */
-
- #ifdef __STDC__
- RX_DECL void
- rx_name_nfa_states (struct rx *rx)
- #else
- RX_DECL void
- rx_name_nfa_states (rx)
- struct rx *rx;
- #endif
- {
- struct rx_nfa_state *n = rx->nfa_states;
-
- rx->nodec = 0;
- rx->epsnodec = -1;
-
- while (n)
- {
- struct rx_nfa_edge *e = n->edges;
-
- if (n->is_start)
- n->eclosure_needed = 1;
-
- while (e)
- {
- switch (e->type)
- {
- case ne_epsilon:
- case ne_side_effect:
- break;
-
- case ne_cset:
- n->id = rx->nodec++;
- {
- struct rx_nfa_edge *from_n = n->edges;
- while (from_n)
- {
- from_n->dest->eclosure_needed = 1;
- from_n = from_n->next;
- }
- }
- goto cont;
- }
- e = e->next;
- }
- n->id = rx->epsnodec--;
- cont:
- n = n->next;
- }
- rx->epsnodec = -rx->epsnodec;
- }
-
-
- /* This page: data structures for the static part of the nfa->supernfa
- * translation.
- */
-
- /* The next several functions compare, construct, etc. lists of side
- * effects. See ECLOSE_NFA (below) for details.
- */
-
- /* Ordering of rx_se_list
- * (-1, 0, 1 return value convention).
- */
-
- #ifdef __STDC__
- static int
- se_list_cmp (void * va, void * vb)
- #else
- static int
- se_list_cmp (va, vb)
- void * va;
- void * vb;
- #endif
- {
- struct rx_se_list * a = (struct rx_se_list *)va;
- struct rx_se_list * b = (struct rx_se_list *)vb;
-
- return ((va == vb)
- ? 0
- : (!va
- ? -1
- : (!vb
- ? 1
- : ((long)a->car < (long)b->car
- ? 1
- : ((long)a->car > (long)b->car
- ? -1
- : se_list_cmp ((void *)a->cdr, (void *)b->cdr))))));
- }
-
-
- #ifdef __STDC__
- static int
- se_list_equal (void * va, void * vb)
- #else
- static int
- se_list_equal (va, vb)
- void * va;
- void * vb;
- #endif
- {
- return !(se_list_cmp (va, vb));
- }
-
- static struct rx_hash_rules se_list_hash_rules =
- {
- se_list_equal,
- compiler_hash_alloc,
- compiler_free_hash,
- compiler_hash_item_alloc,
- compiler_free_hash_item
- };
-
- static DEF_POOL(sel_pool, struct rx_se_list);
-
- #ifdef __STDC__
- static struct rx_se_list *
- side_effect_cons (struct rx * rx,
- void * se, struct rx_se_list * list)
- #else
- static struct rx_se_list *
- side_effect_cons (rx, se, list)
- struct rx * rx;
- void * se;
- struct rx_se_list * list;
- #endif
- {
- struct rx_se_list * l = ((struct rx_se_list *)
- chunk_malloc (&sel_pool));
- if (!l)
- return 0;
- l->car = se;
- l->cdr = list;
- return l;
- }
-
-
- #ifdef __STDC__
- static struct rx_se_list *
- hash_cons_se_prog (struct rx * rx,
- struct rx_hash * memo,
- void * car, struct rx_se_list * cdr)
- #else
- static struct rx_se_list *
- hash_cons_se_prog (rx, memo, car, cdr)
- struct rx * rx;
- struct rx_hash * memo;
- void * car;
- struct rx_se_list * cdr;
- #endif
- {
- long hash = (long)car ^ (long)cdr;
- struct rx_se_list template;
-
- template.car = car;
- template.cdr = cdr;
- {
- struct rx_hash_item * it = rx_hash_store (memo, hash,
- (void *)&template,
- &se_list_hash_rules);
- if (!it)
- return 0;
- if (it->data == (void *)&template)
- {
- struct rx_se_list * consed = ((struct rx_se_list *)
- chunk_malloc (&sel_pool));
- *consed = template;
- it->data = (void *)consed;
- }
- return (struct rx_se_list *)it->data;
- }
- }
-
-
- #ifdef __STDC__
- static struct rx_se_list *
- hash_se_prog (struct rx * rx, struct rx_hash * memo, struct rx_se_list * prog)
- #else
- static struct rx_se_list *
- hash_se_prog (rx, memo, prog)
- struct rx * rx;
- struct rx_hash * memo;
- struct rx_se_list * prog;
- #endif
- {
- struct rx_se_list * answer = 0;
- while (prog)
- {
- answer = hash_cons_se_prog (rx, memo, prog->car, answer);
- if (!answer)
- return 0;
- prog = prog->cdr;
- }
- return answer;
- }
-
-
- /* This page: more data structures for nfa->supernfa. Specificly,
- * sets of nfa states.
- */
-
- #ifdef __STDC__
- static int
- nfa_set_cmp (void * va, void * vb)
- #else
- static int
- nfa_set_cmp (va, vb)
- void * va;
- void * vb;
- #endif
- {
- struct rx_nfa_state_set * a = (struct rx_nfa_state_set *)va;
- struct rx_nfa_state_set * b = (struct rx_nfa_state_set *)vb;
-
- return ((va == vb)
- ? 0
- : (!va
- ? -1
- : (!vb
- ? 1
- : (a->car->id < b->car->id
- ? 1
- : (a->car->id > b->car->id
- ? -1
- : nfa_set_cmp ((void *)a->cdr, (void *)b->cdr))))));
- }
-
- #ifdef __STDC__
- static int
- nfa_set_equal (void * va, void * vb)
- #else
- static int
- nfa_set_equal (va, vb)
- void * va;
- void * vb;
- #endif
- {
- return !nfa_set_cmp (va, vb);
- }
-
- static struct rx_hash_rules nfa_set_hash_rules =
- {
- nfa_set_equal,
- compiler_hash_alloc,
- compiler_free_hash,
- compiler_hash_item_alloc,
- compiler_free_hash_item
- };
-
-
- /* CONS -- again, sets with == elements are ==. */
-
- static DEF_POOL(nfa_sets, struct rx_nfa_state_set);
-
- #ifdef __STDC__
- static struct rx_nfa_state_set *
- nfa_set_cons (struct rx * rx,
- struct rx_hash * memo, struct rx_nfa_state * state,
- struct rx_nfa_state_set * set)
- #else
- static struct rx_nfa_state_set *
- nfa_set_cons (rx, memo, state, set)
- struct rx * rx;
- struct rx_hash * memo;
- struct rx_nfa_state * state;
- struct rx_nfa_state_set * set;
- #endif
- {
- struct rx_nfa_state_set template;
- struct rx_hash_item * node;
- template.car = state;
- template.cdr = set;
- node = rx_hash_store (memo,
- (((long)state) >> 8) ^ (long)set,
- &template, &nfa_set_hash_rules);
- if (!node)
- return 0;
- if (node->data == &template)
- {
- struct rx_nfa_state_set * l = ((struct rx_nfa_state_set *)
- chunk_malloc (&nfa_sets));
- node->data = (void *) l;
- if (!l)
- return 0;
- *l = template;
- }
- return (struct rx_nfa_state_set *)node->data;
- }
-
-
- #ifdef __STDC__
- static struct rx_nfa_state_set *
- nfa_set_enjoin (struct rx * rx,
- struct rx_hash * memo, struct rx_nfa_state * state,
- struct rx_nfa_state_set * set)
- #else
- static struct rx_nfa_state_set *
- nfa_set_enjoin (rx, memo, state, set)
- struct rx * rx;
- struct rx_hash * memo;
- struct rx_nfa_state * state;
- struct rx_nfa_state_set * set;
- #endif
- {
- if (!set || state->id < set->car->id)
- return nfa_set_cons (rx, memo, state, set);
- if (state->id == set->car->id)
- return set;
- else
- {
- struct rx_nfa_state_set * newcdr
- = nfa_set_enjoin (rx, memo, state, set->cdr);
- if (newcdr != set->cdr)
- set = nfa_set_cons (rx, memo, set->car, newcdr);
- return set;
- }
- }
-
-
-
- /* This page: computing epsilon closures. The closures aren't total.
- * Each node's closures are partitioned according to the side effects entailed
- * along the epsilon edges. Return true on success.
- */
-
- struct eclose_frame
- {
- struct rx_se_list *prog_backwards;
- };
-
-
- #ifdef __STDC__
- static int
- eclose_node (struct rx *rx, struct rx_nfa_state *outnode,
- struct rx_nfa_state *node, struct eclose_frame *frame)
- #else
- static int
- eclose_node (rx, outnode, node, frame)
- struct rx *rx;
- struct rx_nfa_state *outnode;
- struct rx_nfa_state *node;
- struct eclose_frame *frame;
- #endif
- {
- struct rx_nfa_edge *e = node->edges;
-
- / cache->lru_superstate = cache->lru_superstate->next_recyclable;
- ++locked_superstates;
- if (locked_superstates == cache->superstates)
- return 0;
- }
- it = cache->lru_superstate;
- it->next_recyclable->prev_recyclable = it->prev_recyclable;
- it->prev_recyclable->next_recyclable = it->next_recyclable;
- cache->lru_superstate = ((it == it->next_recyclable)
- ? 0
- : it->next_recyclable);
- }
-
- if (it->transition_refs)
- {
- struct rx_distinct_future *df;
- for (df = it->transition_refs,
- df->prev_same_dest->next_same_dest = 0;
- df;
- df = df->next_same_dest)
- {
- df->future_frame.inx = cache->instruction_table[rx_cache_miss];
- df->future_frame.data = 0;
- df->future_frame.data_2 = (void *) df;
- df->future = 0;
- }
- it->transition_refs->prev_same_dest->next_same_dest =
- it->transition_refs;
- }
- {
- struct rx_super_edge *tc = it->edges;
- while (tc)
- {
- struct rx_distinct_future * df;
- struct rx_super_edge *tct = tc->next;
- df = tc->options;
- df->next_same_super_edge[1]->next_same_super_edge[0] = 0;
- while (df)
- {
- struct rx_distinct_future *dft = df;
- df = df->next_same_super_edge[0];
-
-
- if (dft->future && dft->future->transition_refs == dft)
- {
- dft->future->transition_refs = dft->next_same_dest;
- if (dft->future->transition_refs == dft)
- dft->future->transition_refs = 0;
- }
- dft->next_same_dest->prev_same_dest = dft->prev_same_dest;
- dft->prev_same_dest->next_same_dest = dft->next_same_dest;
- rx_cache_free (cache, &cache->free_discernable_futures,
- (char *)dft);
- }
- rx_cache_free (cache, &cache->free_transition_classes, (char *)tc);
- tc = tct;
- }
- }
-
- if (it->contents->superstate == it)
- it->contents->superstate = 0;
- release_superset_low (cache, it->contents);
- rx_cache_free (cache, &cache->free_superstates, (char *)it);
- --cache->superstates;
- return 1;
- }
-
- #ifdef __STDC__
- static char *
- rx_cache_get (struct rx_cache * cache,
- struct rx_freelist ** freelist)
- #else
- static char *
- rx_cache_get (cache, freelist)
- struct rx_cache * cache;
- struct rx_freelist ** freelist;
- #endif
- {
- while (!*freelist && rx_really_free_superstate (cache))
- ;
- if (!*freelist)
- return 0;
- {
- struct rx_freelist * it = *freelist;
- *freelist = it->next;
- return (char *)it;
- }
- }
-
- #ifdef __STDC__
- static char *
- rx_cache_malloc_or_get (struct rx_cache * cache,
- struct rx_freelist ** freelist, int bytes)
- #else
- static char *
- rx_cache_malloc_or_get (cache, freelist, bytes)
- struct rx_cache * cache;
- struct rx_freelist ** freelist;
- int bytes;
- #endif
- {
- if (!*freelist)
- {
- char * answer = rx_cache_malloc (cache, bytes);
- if (answer)
- return answer;
- }
-
- return rx_cache_get (cache, freelist);
- }
-
- #ifdef __STDC__
- static char *
- rx_cache_get_superstate (struct rx_cache * cache)
- #else
- static char *
- rx_cache_get_superstate (cache)
- struct rx_cache * cache;
- #endif
- {
- char * answer;
- int bytes = ( sizeof (struct rx_superstate)
- + cache->local_cset_size * sizeof (struct rx_inx));
- if (!cache->free_superstates
- && (cache->superstates < cache->superstates_allowed))
- {
- answer = rx_cache_malloc (cache, bytes);
- if (answer)
- {
- ++cache->superstates;
- return answer;
- }
- }
- answer = rx_cache_get (cache, &cache->free_superstates);
- if (!answer)
- {
- answer = rx_cache_malloc (cache, bytes);
- if (answer)
- ++cache->superstates_allowed;
- }
- ++cache->superstates;
- return answer;
- }
-
-
-
- static int
- supersetcmp (va, vb)
- void * va;
- void * vb;
- {
- struct rx_superset * a = (struct rx_superset *)va;
- struct rx_superset * b = (struct rx_superset *)vb;
- return ( (a == b)
- || (a && b && (a->car == b->car) && (a->cdr == b->cdr)));
- }
-
-
- #ifdef __STDC__
- static struct rx_hash_item *
- superset_allocator (struct rx_hash_rules * rules, void * val)
- #else
- static struct rx_hash_item *
- superset_allocator (rules, val)
- struct rx_hash_rules * rules;
- void * val;
- #endif
- {
- struct rx_cache * cache
- = ((struct rx_cache *)
- ((char *)rules
- - (unsigned long)(&((struct rx_cache *)0)->superset_hash_rules)));
- struct rx_superset * template = (struct rx_superset *)val;
- struct rx_superset * newset
- = ((struct rx_superset *)
- rx_cache_malloc_or_get (cache,
- &cache->free_supersets,
- sizeof (*template)));
- newset->refs = 0;
- newset->car = template->car;
- newset->id = template->car->id;
- newset->cdr = template->cdr;
- newset->superstate = 0;
- rx_protect_superset (rx, template->cdr);
- newset->hash_item.data = (void *)newset;
- newset->hash_item.binding = 0;
- return &newset->hash_item;
- }
-
- #ifdef __STDC__
- static struct rx_hash *
- super_hash_allocator (struct rx_hash_rules * rules)
- #else
- static struct rx_hash *
- super_hash_allocator (rules)
- struct rx_hash_rules * rules;
- #endif
- {
- struct rx_cache * cache
- = ((struct rx_cache *)
- ((char *)rules
- - (unsigned long)(&((struct rx_cache *)0)->superset_hash_rules)));
- return ((struct rx_hash *)
- rx_cache_malloc_or_get (cache,
- &cache->free_hash, sizeof (struct rx_hash)));
- }
-
-
- #ifdef __STDC__
- static void
- super_hash_liberator (struct rx_hash * hash, struct rx_hash_rules * rules)
- #else
- static void
- super_hash_liberator (hash, rules)
- struct rx_hash * hash;
- struct rx_hash_rules * rules;
- #endif
- {
- struct rx_cache * cache
- = ((struct rx_cache *)
- (char *)rules - (long)(&((struct rx_cache *)0)->superset_hash_rules));
- rx_cache_free (cache, &cache->free_hash, (char *)hash);
- }
-
- #ifdef __STDC__
- static void
- superset_hash_item_liberator (struct rx_hash_item * it,
- struct rx_hash_rules * rules)
- #else
- static void
- superset_hash_item_liberator (it, rules) /* Well, it does ya know. */
- struct rx_hash_item * it;
- struct rx_hash_rules * rules;
- #endif
- {
- }
-
- int rx_cache_bound = 128;
- static int rx_default_cache_got = 0;
-
- #ifdef __STDC__
- static int
- bytes_for_cache_size (int supers, int cset_size)
- #else
- static int
- bytes_for_cache_size (supers, cset_size)
- int supers;
- int cset_size;
- #endif
- {
- return (int)
- ((float)supers *
- ( (1.03 * (float) ( rx_sizeof_bitset (cset_size)
- + sizeof (struct rx_super_edge)))
- + (1.80 * (float) sizeof (struct rx_possible_future))
- + (float) ( sizeof (struct rx_superstate)
- + cset_size * sizeof (struct rx_inx))));
- }
-
- #ifdef __STDC__
- static void
- rx_morecore (struct rx_cache * cache)
- #else
- static void
- rx_morecore (cache)
- struct rx_cache * cache;
- #endif
- {
- if (rx_default_cache_got >= rx_cache_bound)
- return;
-
- rx_default_cache_got += 16;
- cache->superstates_allowed = rx_cache_bound;
- {
- struct rx_blocklist ** pos = &cache->memory;
- int size = bytes_for_cache_size (16, cache->local_cset_size);
- while (*pos)
- pos = &(*pos)->next;
- *pos = ((struct rx_blocklist *)
- malloc (size + sizeof (struct rx_blocklist)));
- if (!*pos)
- return;
-
- (*pos)->next = 0;
- (*pos)->bytes = size;
- cache->memory_pos = *pos;
- cache->memory_addr = (char *)*pos + sizeof (**pos);
- cache->bytes_left = size;
- }
- }
-
- static struct rx_cache default_cache =
- {
- {
- supersetcmp,
- super_hash_allocator,
- super_hash_liberator,
- superset_allocator,
- superset_hash_item_liberator,
- },
- 0,
- 0,
- 0,
- 0,
- rx_morecore,
-
- 0,
- 0,
- 0,
- 0,
- 0,
-
- 0,
- 0,
-
- 0,
-
- 0,
- 0,
- 0,
- 0,
- 128,
-
- 256,
- rx_id_instruction_table,
-
- {
- 0,
- 0,
- {0},
- {0},
- {0}
- }
- };
-
- /* This adds an element to a superstate set. These sets are lists, such
- * that lists with == elements are ==. The empty set is returned by
- * superset_cons (rx, 0, 0) and is NOT equivelent to
- * (struct rx_superset)0.
- */
-
- #ifdef __STDC__
- RX_DECL struct rx_superset *
- rx_superset_cons (struct rx * rx,
- struct rx_nfa_state *car, struct rx_superset *cdr)
- #else
- RX_DECL struct rx_superset *
- rx_superset_cons (rx, car, cdr)
- struct rx * rx;
- struct rx_nfa_state *car;
- struct rx_superset *cdr;
- #endif
- {
- struct rx_cache * cache = rx->cache;
- if (!car && !cdr)
- {
- if (!cache->empty_superset)
- {
- cache->empty_superset
- = ((struct rx_su _frame.inx = rx->instruction_table[rx_cache_miss];
- dfp->future_frame.data = 0;
- dfp->future_frame.data_2 = (void *) dfp;
- dfp->side_effects_frame.inx
- = rx->instruction_table[rx_do_side_effects];
- dfp->side_effects_frame.data = 0;
- dfp->side_effects_frame.data_2 = (void *) dfp;
- dfp->effects = future->effects;
- }
- }
- return df;
- }
-
-
-
-
- /* This constructs a new superstate from its state set. The only
- * complexity here is memory management.
- */
- #ifdef __STDC__
- RX_DECL struct rx_superstate *
- rx_superstate (struct rx *rx,
- struct rx_superset *set)
- #else
- RX_DECL struct rx_superstate *
- rx_superstate (rx, set)
- struct rx *rx;
- struct rx_superset *set;
- #endif
- {
- struct rx_cache * cache = rx->cache;
- struct rx_superstate * superstate = 0;
-
- /* Does the superstate already exist in the cache? */
- if (set->superstate)
- {
- if (set->superstate->rx_id != rx->rx_id)
- {
- /* Aha. It is in the cache, but belongs to a superstate
- * that refers to an NFA that no longer exists.
- * (We know it no longer exists because it was evidently
- * stored in the same region of memory as the current nfa
- * yet it has a different id.)
- */
- superstate = set->superstate;
- if (!superstate->is_semifree)
- {
- if (cache->lru_superstate == superstate)
- {
- cache->lru_superstate = superstate->next_recyclable;
- if (cache->lru_superstate == superstate)
- cache->lru_superstate = 0;
- }
- {
- superstate->next_recyclable->prev_recyclable
- = superstate->prev_recyclable;
- superstate->prev_recyclable->next_recyclable
- = superstate->next_recyclable;
- if (!cache->semifree_superstate)
- {
- (cache->semifree_superstate
- = superstate->next_recyclable
- = superstate->prev_recyclable
- = superstate);
- }
- else
- {
- superstate->next_recyclable = cache->semifree_superstate;
- superstate->prev_recyclable
- = cache->semifree_superstate->prev_recyclable;
- superstate->next_recyclable->prev_recyclable
- = superstate;
- superstate->prev_recyclable->next_recyclable
- = superstate;
- cache->semifree_superstate = superstate;
- }
- ++cache->semifree_superstates;
- }
- }
- set->superstate = 0;
- goto handle_cache_miss;
- }
- ++cache->hits;
- superstate = set->superstate;
-
- rx_refresh_this_superstate (cache, superstate);
- return superstate;
- }
-
- handle_cache_miss:
-
- /* This point reached only for cache misses. */
- ++cache->misses;
- #if RX_DEBUG
- if (rx_debug_trace > 1)
- {
- struct rx_superset * setp = set;
- fprintf (stderr, "Building a superstet %d(%d): ", rx->rx_id, set);
- while (setp)
- {
- fprintf (stderr, "%d ", setp->id);
- setp = setp->cdr;
- }
- fprintf (stderr, "(%d)\n", set);
- }
- #endif
- superstate = (struct rx_superstate *)rx_cache_get_superstate (cache);
- if (!superstate)
- return 0;
-
- if (!cache->lru_superstate)
- (cache->lru_superstate
- = superstate->next_recyclable
- = superstate->prev_recyclable
- = superstate);
- else
- {
- superstate->next_recyclable = cache->lru_superstate;
- superstate->prev_recyclable = cache->lru_superstate->prev_recyclable;
- ( superstate->prev_recyclable->next_recyclable
- = superstate->next_recyclable->prev_recyclable
- = superstate);
- }
- superstate->rx_id = rx->rx_id;
- superstate->transition_refs = 0;
- superstate->locks = 0;
- superstate->is_semifree = 0;
- set->superstate = superstate;
- superstate->contents = set;
- rx_protect_superset (rx, set);
- superstate->edges = 0;
- {
- int x;
- /* None of the transitions from this superstate are known yet. */
- for (x = 0; x < rx->local_cset_size; ++x) /* &&&&& 3.8 % */
- {
- struct rx_inx * ifr = &superstate->transitions[x];
- ifr->inx = rx->instruction_table [rx_cache_miss];
- ifr->data = ifr->data_2 = 0;
- }
- }
- return superstate;
- }
-
-
- /* This computes the destination set of one edge of the superstate NFA.
- * Note that a RX_DISTINCT_FUTURE is a superstate edge.
- * Returns 0 on an allocation failure.
- */
-
- #ifdef __STDC__
- static int
- solve_destination (struct rx *rx, struct rx_distinct_future *df)
- #else
- static int
- solve_destination (rx, df)
- struct rx *rx;
- struct rx_distinct_future *df;
- #endif
- {
- struct rx_super_edge *tc = df->edge;
- struct rx_superset *nfa_state;
- struct rx_superset *nil_set = rx_superset_cons (rx, 0, 0);
- struct rx_superset *solution = nil_set;
- struct rx_superstate *dest;
-
- /* Iterate over all NFA states in the state set of this superstate. */
- for (nfa_state = df->present->contents;
- nfa_state->car;
- nfa_state = nfa_state->cdr)
- {
- struct rx_nfa_edge *e;
- /* Iterate over all edges of each NFA state. */
- for (e = nfa_state->car->edges; e; e = e->next)
- /* If we find an edge that is labeled with
- * the characters we are solving for.....
- */
- if (rx_bitset_is_subset (rx->local_cset_size,
- tc->cset, e->params.cset))
- {
- struct rx_nfa_state *n = e->dest;
- struct rx_possible_future *pf;
- /* ....search the partial epsilon closures of the destination
- * of that edge for a path that involves the same set of
- * side effects we are solving for.
- * If we find such a RX_POSSIBLE_FUTURE, we add members to the
- * stateset we are computing.
- */
- for (pf = n->futures; pf; pf = pf->next)
- if (pf->effects == df->effects)
- {
- struct rx_superset * old_sol = solution;
- rx_protect_superset (rx, solution);
- solution =
- rx_superstate_eclosure_union (rx, solution, pf->destset);
- if (!solution)
- return 0;
- rx_release_superset (rx, old_sol);
- }
- }
- }
- /* It is possible that the RX_DISTINCT_FUTURE we are working on has
- * the empty set of NFA states as its definition. In that case, this
- * is a failure point.
- */
- if (solution == nil_set)
- {
- df->future_frame.inx = (void *) rx_backtrack;
- df->future_frame.data = 0;
- df->future_frame.data_2 = 0;
- return 1;
- }
- rx_protect_superset (rx, solution);
- dest = rx_superstate (rx, solution);
- rx_release_superset (rx, solution);
- if (!dest)
- return 0;
-
- {
- struct rx_distinct_future *dft;
- dft = df;
- df->prev_same_dest->next_same_dest = 0;
- while (dft)
- {
- dft->future = dest;
- dft->future_frame.inx = rx->instruction_table[rx_next_char];
- dft->future_frame.data = (void *) dest->transitions;
- dft = dft->next_same_dest;
- }
- df->prev_same_dest->next_same_dest = df;
- }
- if (!dest->transition_refs)
- dest->transition_refs = df;
- else
- {
- struct rx_distinct_future *dft = dest->transition_refs->next_same_dest;
- dest->transition_refs->next_same_dest = df->next_same_dest;
- df->next_same_dest->prev_same_dest = dest->transition_refs;
- df->next_same_dest = dft;
- dft->prev_same_dest = df;
- }
- return 1;
- }
-
-
- /* This takes a superstate and a character, and computes some edges
- * from the superstate NFA. In particular, this computes all edges
- * that lead from SUPERSTATE given CHR. This function also
- * computes the set of characters that share this edge set.
- * This returns 0 on allocation error.
- * The character set and list of edges are returned through
- * the paramters CSETOUT and DFOUT.
- } */
-
- #ifdef __STDC__
- static int
- compute_super_edge (struct rx *rx, struct rx_distinct_future **dfout,
- rx_Bitset csetout, struct rx_superstate *superstate,
- unsigned char chr)
- #else
- static int
- compute_super_edge (rx, dfout, csetout, superstate, chr)
- struct rx *rx;
- struct rx_distinct_future **dfout;
- rx_Bitset csetout;
- struct rx_superstate *superstate;
- unsigned char chr;
- #endif
- {
- struct rx_superset *stateset = superstate->contents;
-
- /* To compute the set of characters that share edges with CHR,
- * we start with the full character set, and subtract.
- */
- rx_bitset_universe (rx->local_cset_size, csetout);
- *dfout = 0;
-
- /* Iterate over the NFA states in the superstate state-set. */
- while (stateset->car)
- {
- struct rx_nfa_edge *e;
- for (e = stateset->car->edges; e; e = e->next)
- if (RX_bitset_member (e->params.cset, chr))
- {
-